package com.maben.netty.udp;

import com.maben.netty.udp.handler.UdpClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.Unpooled;
import io.netty.channel.Channel;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.nio.NioDatagramChannel;
import io.netty.util.CharsetUtil;
import io.netty.util.concurrent.DefaultThreadFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.net.InetSocketAddress;

@Component
public class UdpClient {

    @Value("${netty.udp.server.host:localhost}")
    private String serverHost;

    @Value("${netty.udp.port:8090}")
    private int serverPort;

    private Channel channel;
    private EventLoopGroup group;

    /**
     * 初始化客户端
     */
    @PostConstruct
    private void init() throws InterruptedException {
        group = new NioEventLoopGroup(new DefaultThreadFactory("netty-udp-client"));
        
        Bootstrap bootstrap = new Bootstrap();
        bootstrap.group(group)
                .channel(NioDatagramChannel.class)
                .option(ChannelOption.SO_BROADCAST, true)
                .handler(new UdpClientHandler());

        channel = bootstrap.bind(0).sync().channel(); // 绑定一个随机端口
        System.out.println(Thread.currentThread()+",客户端初始化成功");
    }

    /**
     * 发送消息到服务器
     */
    public void sendMessage(String message) {
        if (channel == null) {
            throw new IllegalStateException(Thread.currentThread()+",UDP客户端未初始化，请先调用init()方法");
        }
        
        // 发送消息到服务器
        channel.writeAndFlush(new DatagramPacket(
                Unpooled.copiedBuffer(message, CharsetUtil.UTF_8),
                new InetSocketAddress(serverHost, serverPort)
        ));
    }

    /**
     * 关闭客户端
     */
    @PreDestroy
    private void close() throws InterruptedException {
        if (channel != null) {
            channel.close().sync();
        }
        if (group != null) {
            group.shutdownGracefully().sync();
        }
    }
}
    